#include <QDebug>
#include "databaseexplorermodel.h"
#include <client/dbclient.h>
using namespace mongo;


DatabaseExplorerModel::DatabaseExplorerModel(QObject* parent)
    :QAbstractItemModel(parent)
{
    rootNode=new Node(Node::Root,tr("MongoDB"));
    rootNode->parent=NULL;
}

DatabaseExplorerModel::~DatabaseExplorerModel()
{
    delete rootNode;
}


int DatabaseExplorerModel::rowCount(const QModelIndex &parent) const
{
    if(parent.column()>0)
        return 0;
    Node* parentNode=nodeFromIndex(parent);
    if(!parentNode)
        return 0;
    return parentNode->children.count();
}

int DatabaseExplorerModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}


QModelIndex DatabaseExplorerModel::index(int row, int column, const QModelIndex &parent) const
{
    //qDebug()<<"row:"<<row<<" column:"<<column<<"\n";
    if(!rootNode || row<0 ||column<0)
        return QModelIndex();
    Node* parentNode=nodeFromIndex(parent);
    Node* childNode=parentNode->children.value(row);
    //qDebug(childNode->str.toStdString().c_str());
    if(!childNode)
        return QModelIndex();
    return createIndex(row,column,childNode);
}

QModelIndex DatabaseExplorerModel::parent(const QModelIndex &child) const
{
    Node* node=nodeFromIndex(child);
    //qDebug()<<"parent:"<<node->str.toStdString().c_str()<<"\n";
    if(!node)
        return QModelIndex();
    Node* parentNode=node->parent;

    if(!parentNode)
    {
        if(node==rootNode)
            return createIndex(0,0,rootNode);
        return QModelIndex();
    }
    Node* grandparentNode=parentNode->parent;

    if(!grandparentNode)
        return QModelIndex();
    int row=grandparentNode->children.indexOf(parentNode);
    return createIndex(row,0,parentNode);
}

QVariant DatabaseExplorerModel::data(const QModelIndex &index, int role) const
{
    if(role!=Qt::DisplayRole)
        return QVariant();
    Node* node=nodeFromIndex(index);
    //qDebug()<<"index:("<<index.row()<<":"<<index.column()<<")data:"<<"type:"<<node->type<<"str:"<<node->str.toStdString().c_str()<<"\n";
    if(!node)
        return QVariant();
    if(index.column()==0){
        //qDebug()<<"NodeType:"<<node->type<<"\n";
        return node->str;
//        switch(node->type){
//        case Node::Root:
//            return tr("MongoDB");
//        case Node::Connection
//            return tr("Connection");
//        case Node::Database:
//            return node->str.toStdString().c_str();
//        case Node::Collection:
//            return tr("Collection");
//        case Node::Document:
//            return tr("Document");
//        default:
//            return tr("Unknown");
//        }
    }
    return QVariant();
}

Node* DatabaseExplorerModel::nodeFromIndex(const QModelIndex& index) const
{
    if(index.isValid()){
        return static_cast<Node* >(index.internalPointer());
    }else{
        return rootNode;
    }
}

QVariant DatabaseExplorerModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation==Qt::Horizontal && role == Qt::DisplayRole){
        if(section==0){
            return tr("Explorer");
        }
    }
    return QVariant();
}


Node::Node(Type type,const QString &str)
{
    this->type = type;
    this->str = str;
    parent = NULL;
}

Node::~Node()
{
    //qDebug()<<"destruct node type:"<<type<<"\n";
    qDeleteAll(children);

}

void DatabaseExplorerModel::buildChildNodes(Node *connectNode,DBClientConnection& clientConnection)
{
    if(NULL==connectNode)
    {
        return ;
    }
    //build connection node
    rootNode->children.push_back(connectNode);
    connectNode->parent=rootNode;

    //connnection sub nodes
    // node level likes that:
    /*  --connectionName
     *    --dbName
     *      --user(prefix db.system.users)
     *      --js  (prefix db.system.js)
     *      --file (prefix db.fs.files)
     *      --index (prefix db.system.indexes)
     *      --collection
     *        --coll1
     *        --coll2
     *    --dbName
     *
     */
    list<string> databaseNames=clientConnection.getDatabaseNames();
    list<string>::iterator databaseNameIter=databaseNames.begin();
    while(databaseNameIter!=databaseNames.end())
    {
        Node* databaseNode=new Node(Node::Database,databaseNameIter->c_str());

        connectNode->children.push_back(databaseNode);
        databaseNode->parent=connectNode;

        Node* usersRootNode=new Node(Node::User,tr("Users"));
        databaseNode->children.push_back(usersRootNode);
        usersRootNode->parent=databaseNode;

        Node* jsRootNode=new Node(Node::Javascript,tr("JavaScript"));
        databaseNode->children.push_back(jsRootNode);
        jsRootNode->parent=databaseNode;

        Node* fsRootNode=new Node(Node::GridFS,tr("GridFS"));
        databaseNode->children.push_back(fsRootNode);
        fsRootNode->parent=databaseNode;

        Node* collRootNode=new Node(Node::Collection,tr("Collections"));
        databaseNode->children.push_back(collRootNode);
        collRootNode->parent=databaseNode;

        list<string> collectionNames=clientConnection.getCollectionNames(*databaseNameIter);
        list<string>::iterator collectionNameIter=collectionNames.begin();
        while(collectionNameIter!=collectionNames.end())
        {
            Node* collectionNode=new Node(Node::Collection,collectionNameIter->c_str());
            collRootNode->children.push_back(collectionNode);
            collectionNode->parent=collRootNode;
            ++collectionNameIter;
        }

        ++databaseNameIter;
    }

    /*
    qDebug("---------------setRootNode-------------------");
    qDebug(node->str.toStdString().c_str());
    if(rootNode->children.count()>0)
    {
        for(int i=0;i<rootNode->children.count();i++)
        {
            Node* connectionNode=node->children[i];
            qDebug()<<"connectionNode:"<<connectionNode->str.toStdString().c_str()<<" type:"<<connectionNode->type<<"\n";
            if(connectionNode->children.count()>0)
            {
                for(int i=0;i<connectionNode->children.count();i++)
                {
                    qDebug()<<"database:"<<connectionNode->children[i]->str.toStdString().c_str()<<" type:"<<connectionNode->children[i]->type<<"\n";
                }

            }
        }
    }
    qDebug("---------------setRootNode-------------------");
    */
    reset();
}

